package com.zbkj.admin.controller;


import cloud.tianai.captcha.application.ImageCaptchaApplication;
import cloud.tianai.captcha.application.vo.CaptchaResponse;
import cloud.tianai.captcha.application.vo.ImageCaptchaVO;
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
import cloud.tianai.captcha.common.response.ApiResponse;
import cloud.tianai.captcha.spring.plugins.secondary.SecondaryVerificationApplication;
import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.validation.ValidationUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zbkj.admin.boot.redisson.command.Redis;
import com.zbkj.admin.boot.redisson.ratelimiter.RateLimiter;
import com.zbkj.admin.constants.SmsConstants;
import com.zbkj.admin.model.user.User;
import com.zbkj.admin.pojo.EbUserRelationshipEntity;
import com.zbkj.admin.request.PasswordRequest;
import com.zbkj.admin.request.UserAddInfoRequest;
import com.zbkj.admin.request.UserBindingPhoneUpdateRequest;
import com.zbkj.admin.request.UserEditInfoRequest;
import com.zbkj.admin.response.UserInfoResponse;
import com.zbkj.admin.response.UserLogoffBeforeResponse;
import com.zbkj.admin.result.CommonResult;
import com.zbkj.admin.service.EbUserRelationshipService;
import com.zbkj.admin.service.UserService;
import com.zbkj.admin.third_party.SMSSendApi;
import com.zbkj.admin.third_party.vo.SMSVo;
import com.zbkj.admin.util.CommonUtil;
import com.zbkj.admin.util.CrmebUtil;
import com.zbkj.admin.util.RC4Util;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.result.R;
import net.dreamlu.mica.core.utils.WebUtil;
import org.dromara.sms4j.aliyun.config.AlibabaConfig;
import org.dromara.sms4j.aliyun.service.AlibabaSmsImpl;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.WebAsyncTask;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;

/**
 * 用户 -- 用户中心
 * +----------------------------------------------------------------------
 * | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
 * +----------------------------------------------------------------------
 * | Author: CRMEB Team <admin@crmeb.com>
 * +----------------------------------------------------------------------
 */
@Slf4j
@RestController
@RequestMapping("api/front/user")
@Tag(name = "用户控制器")
public class UserFrontController {

    @Autowired
    private Redis redis;
    @Autowired
    private SMSSendApi smsSendApi;
    @Autowired
    private UserService userService;
    @Autowired
    private ImageCaptchaApplication imageCaptcha;
    @Autowired
    private EbUserRelationshipService userRelationshipService;

    @Operation(summary = "获取手机号码")
//    @RateLimiter(value = "sms:validate:request", param = "#phone", max = 1)
    @RequestMapping(value = "/getPhone", method = RequestMethod.GET)
    public R<String> getPhone() {
        User info = userService.getInfo();
        if (info == null) {
            return R.fail("请先登录");
        }
        return R.success(info.getPhone());
    }

    @Operation(summary = "手机号修改密码获取验证码")
    @RateLimiter(value = "sms:validate:request", param = "T(net.dreamlu.mica.core.utils.WebUtil).getRequest().getParameter('phone')", max = 1,
            msg = "您请求过于频繁")
    @RequestMapping(value = "/smsCode", method = RequestMethod.GET)
    public R<Boolean> smsCode(@RequestParam("phone") String phone,
                              @RequestParam(value = "type") long type,
                              @RequestParam(value = "validToken", required = false) String validToken
    ) {
        if (StrUtil.isNotBlank(validToken) && type != 71L) {
            boolean valid = ((SecondaryVerificationApplication) imageCaptcha).secondaryVerification(validToken);
            if (!valid) {
                return R.fail("请先验证图片验证码");
            }
        } else if (type != 71L) {
            return R.fail("请先验证图片验证码");
        }
//        String code = RandomUtil.randomString("0123456789", 6);
//        String format = StrUtil.format("【广州仓鼠智选】您的验证码为: {},5分钟内有效。请勿将验证码泄露他人！", code);
//        JSONObject send = smsSendApi.send(SMSVo.builder().appKey("9a209fff2dad8fba75bec2945126dd2a")
//                .appSecret("Gzcszx=1").data(SMSVo.SMSInfoVo.builder().addPhone(phone).msg(format).build()).build());
//        if (!send.getStr("code").equalsIgnoreCase("1")) {
//            return R.fail(send.getStr("msg"));
//        }
//        redis.setEx(SmsConstants.SMS_VALIDATE_PHONE + phone, code, Duration.ofMinutes(5));
//        return R.success(true);
        if (type != 71L) {
            return R.fail("无法发送短信");
        }
        if (!Validator.isMobile(phone)) {
            return R.fail("手机号码格式不对");
        }
        String code = RandomUtil.randomString("0123456789", 6);
        LinkedHashMap<String, String> messages = new LinkedHashMap<>();
        messages.put("code", code);
        SmsBlend smsBlend = SmsFactory.getSmsBlend("tx1");
        SmsResponse smsResponse = smsBlend.sendMessage(phone, messages);
        if (smsResponse.isSuccess()) {
            redis.setEx(SmsConstants.SMS_VALIDATE_PHONE + phone, code, Duration.ofMinutes(5));
            return R.success(true);
        }
        return R.fail(String.valueOf(smsResponse.getData()));
    }

    @GetMapping("/genCaptcha")
    public CaptchaResponse<ImageCaptchaVO> genCaptcha() {
        // 1.生成验证码(该数据返回给前端用于展示验证码数据)
        // 参数1为具体的验证码类型， 默认支持 SLIDER、ROTATE、WORD_IMAGE_CLICK、CONCAT 等验证码类型，详见： `CaptchaTypeConstant`类
        return imageCaptcha.generateCaptcha(CaptchaTypeConstant.SLIDER);
    }

    @PostMapping("/check")
    public ApiResponse<?> checkCaptcha(@RequestBody Data data) {
        ApiResponse<?> response = imageCaptcha.matching(data.getId(), data.getData());
        if (response.isSuccess()) {
            // 验证码验证成功，此处应该进行自定义业务处理， 或者返回验证token进行二次验证等。
            return ApiResponse.ofSuccess(Collections.singletonMap("validToken", data.getId()));
        }
        return response;
    }

    @lombok.Data
    public static class Data {
        // 验证码id
        private String id;
        // 验证码数据
        private ImageCaptchaTrack data;
        // 可以加用户自定义业务参数...
    }

    @Operation(summary = "手机号获取验证码的图形校验")
    @RequestMapping(value = "/checkSmsCode", method = RequestMethod.POST)
    public R<Boolean> checkSmsCode(@RequestParam(value = "sceneId", required = false) String sceneId,
                                   @RequestParam(value = "captchaVerifyParam", required = false) String captchaVerifyParam) throws Exception {
        String body = JakartaServletUtil.getBody(WebUtil.getRequest());
        if (StrUtil.isBlank(body) && StrUtil.isBlank(sceneId) && StrUtil.isBlank(captchaVerifyParam)) {
            return R.fail("请先验证图片验证码");
        }
        if (StrUtil.isNotBlank(body)) {
            JSONObject jsonObject = JSON.parseObject(body, JSONObject.class);
            sceneId = jsonObject.getString("sceneId");
            captchaVerifyParam = jsonObject.getString("captchaVerifyParam");
        }
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
/*        SmsBlend smsBlend = SmsFactory.getSmsBlend("tx1");
        AlibabaConfig configInfo;
        // 修改方案2：使用Spring工具类获取代理目标对象
        if (AopUtils.isAopProxy(smsBlend)) {
            Object target = AopProxyUtils.getSingletonTarget(smsBlend);
            if (target instanceof AlibabaSmsImpl info) {
                 configInfo = (AlibabaConfig) ReflectUtil.getFieldValue(info, "config");
            }
        }*/
//        Object blend = ReflectUtil.getFieldValue(smsBlend, "h");
//        AlibabaSmsImpl blend1 = (AlibabaSmsImpl)ReflectUtil.getFieldValue(blend, "smsBlend");
//        AlibabaSmsImpl smsBlend1 = (AlibabaSmsImpl) smsBlend;
//        AlibabaConfig configInfo = (AlibabaConfig) ReflectUtil.getFieldValue(smsBlend, "config");
        config.accessKeyId = "LTAI5tPEPmqXvDYc1N9LEPdd";
        config.accessKeySecret = "mTr2n71LxPgDEIvFqCArYQw25M5mXO";
        config.endpoint = "captcha.cn-shanghai.aliyuncs.com";
        // 设置连接超时为5000毫秒
        config.connectTimeout = 5000;
        // 设置读超时为5000毫秒
        config.readTimeout = 5000;
        com.aliyun.captcha20230305.Client client = new com.aliyun.captcha20230305.Client(config);
        com.aliyun.captcha20230305.models.VerifyIntelligentCaptchaRequest request = new com.aliyun.captcha20230305.models.VerifyIntelligentCaptchaRequest();
        request.captchaVerifyParam = captchaVerifyParam;
        request.sceneId = sceneId;
        com.aliyun.captcha20230305.models.VerifyIntelligentCaptchaResponse resp = client.verifyIntelligentCaptcha(request);
        Boolean captchaVerifyResult = resp.body.result.verifyResult;
        if (captchaVerifyResult) {
            return R.success(resp.body.result.verifyResult);
        }
        return R.fail(resp.body.getMessage());
    }

    @Operation(summary = "手机号修改密码获取验证码")
    @RequestMapping(value = "/update/password/phone/code", method = RequestMethod.POST)
    public CommonResult<String> getUpdatePasswordPhoneCode() {
        if (userService.getUpdatePasswordPhoneCode()) {
            return CommonResult.success();
        }
        return CommonResult.failed();
    }

    @Operation(summary = "手机号修改密码")
    @RequestMapping(value = "/register/reset", method = RequestMethod.POST)
    public CommonResult<Boolean> password(@RequestBody @Validated PasswordRequest request) {
        return CommonResult.success(userService.password(request));
    }

    @Operation(summary = "修改个人信息")
    @RequestMapping(value = "/user/edit", method = RequestMethod.POST)
    public CommonResult<String> personInfo(@RequestBody @Validated UserEditInfoRequest request) {
        if (userService.editUser(request)) {
            return CommonResult.success();
        }
        return CommonResult.failed();
    }

    @Operation(summary = "修改个人信息")
    @RequestMapping(value = "/isBuild", method = RequestMethod.GET)
    public WebAsyncTask<CommonResult<Boolean>> isBuild() {
        User info = userService.getInfo();
        EbUserRelationshipEntity relationshipEntity = userRelationshipService.getOne(userRelationshipService.from().eq(EbUserRelationshipEntity::getUid, info.getId())
                .eq(EbUserRelationshipEntity::getIsEstablish, 1));
        if (Objects.isNull(relationshipEntity)) {
            return new WebAsyncTask<>(3000L, () -> CommonResult.success(false));
        } else {
            return new WebAsyncTask<>(3000L, () -> CommonResult.success(true));
        }
    }

    @Operation(summary = "手动填写邀请码邀请上级")
    @RequestMapping(value = "/user/build", method = RequestMethod.GET)
    public WebAsyncTask<CommonResult<Boolean>> build(@RequestParam("code") String code) {
//        String encrypt = RC4Util.encrypt("606");
        String decrypt = "";
        try {
            decrypt = RC4Util.decrypt(Long.parseLong(code));
        } catch (Exception e) {
            return new WebAsyncTask<>(3000L, () -> CommonResult.failed("邀请码识别错误"));
        }
        if (StrUtil.isBlank(decrypt)) {
            return new WebAsyncTask<>(3000L, () -> CommonResult.failed("邀请码错误"));
        }
        User info = userService.getInfo();
        if (Objects.isNull(info)) {
            return new WebAsyncTask<>(3000L, () -> CommonResult.failed("请登录后再绑定邀请码"));
        }

        EbUserRelationshipEntity relationshipEntity = userRelationshipService.getOne(userRelationshipService.from().eq(EbUserRelationshipEntity::getUid, info.getId())
                .eq(EbUserRelationshipEntity::getIsEstablish, 1));

//        EbUserRelationshipEntity relationshipEntityData = userRelationshipService.getOne(userRelationshipService.from().eq(EbUserRelationshipEntity::getUid, info.getId())
//                .eq(EbUserRelationshipEntity::getIsEstablish, 0)
//                .eq(EbUserRelationshipEntity::getPId, Integer.parseInt(decrypt)));

        EbUserRelationshipEntity relationshipEntities = userRelationshipService.getOne(userRelationshipService.from().eq(EbUserRelationshipEntity::getUid, info.getId())
                .eq(EbUserRelationshipEntity::getIsEstablish, 0));

        if (Objects.nonNull(relationshipEntity)) {
            return new WebAsyncTask<>(3000L, () -> CommonResult.failed("此邀请码已绑定"));
        }

        if (String.valueOf(info.getId()).equalsIgnoreCase(decrypt)) {
            return new WebAsyncTask<>(3000L, () -> CommonResult.failed("不能邀请自己"));
        }

        if (Objects.nonNull(relationshipEntities)) {
            userRelationshipService.updateById(relationshipEntities.setPId(Long.valueOf(decrypt)));
            return new WebAsyncTask<>(3000L, () -> CommonResult.success(true));
        }

        if (Validator.isNumber(decrypt)) {
            EbUserRelationshipEntity relationshipEntity1 = userRelationshipService.getOne(userRelationshipService.from()
                    .where(EbUserRelationshipEntity::getUid).eq(Long.valueOf(decrypt))
                    .eq(EbUserRelationshipEntity::getPId, 0)
                    .eq(EbUserRelationshipEntity::getIsEstablish, 1)
            );
            // 新用户默认上级
            if (Objects.isNull(relationshipEntity1)) {
                userRelationshipService.save(EbUserRelationshipEntity.builder()
                        .uid(Long.valueOf(info.getId())).pId(0L)
                        .isFirstOrder(1).isEstablish(1).createTime(LocalDateTime.now()).build());
            }
            userRelationshipService.save(EbUserRelationshipEntity.builder()
                    .uid(Long.valueOf(info.getId())).pId(Long.valueOf(decrypt))
                    .isFirstOrder(1).isEstablish(0).createTime(LocalDateTime.now()).build());
            return new WebAsyncTask<>(3000L, () -> CommonResult.success(true));
        } else {
            return new WebAsyncTask<>(3000L, () -> CommonResult.failed("邀请码不合法"));
        }
    }


    @Operation(summary = "创建个人信息")
    @RequestMapping(value = "/user/register", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Integer> add(@RequestBody @Validated UserAddInfoRequest request) {
        String pwd = "";
        User one = userService.getOne(Wrappers.<User>lambdaQuery()
                .eq(User::getPhone, request.getPhone()).eq(User::getIsLogoff, false));
        if (Objects.nonNull(one)) {
            return CommonResult.failed("手机号已注册");
        }
        if (!Validator.isMobile(request.getPhone())) {
            return CommonResult.failed("手机号码格式不对");
        }
        if (StrUtil.isBlank(request.getCode())) {
            return CommonResult.failed("验证码不能为空");
        }
        if (!Validator.isNumber(request.getCode())) {
            return CommonResult.failed("请输入数字验证码");
        }
        if (StrUtil.isBlank(request.getPassword())) {
            return CommonResult.failed("密码不能为空");
        }
        if (StrUtil.isBlank(request.getPasswordNew())) {
            return CommonResult.failed("确认密码不能为空");
        }
        if (request.getPassword().equalsIgnoreCase(request.getPasswordNew())) {
            pwd = CrmebUtil.encryptPassword(request.getPassword(), request.getPhone());
        }
        if (StrUtil.isBlank(request.getPhone())) {
            return CommonResult.failed("密码不能为空");
        }
//        String code = redis.get(SmsConstants.SMS_VALIDATE_PHONE + request.getPhone());
//        if (StrUtil.isBlank(code)) {
//            return CommonResult.failed("验证码已过期");
//        }
//        if (!code.equalsIgnoreCase(request.getCode())) {
//            return CommonResult.failed("验证码错误");
//        }
//        redis.del(SmsConstants.SMS_VALIDATE_PHONE + request.getPhone());
        User user = BeanUtil.copyProperties(request, User.class);
        user.setPwd(pwd).setAccount(request.getPhone());
        // 绑定推荐人

        userService.save(user);
        if (StrUtil.isNotBlank(request.getPrentId()) || StrUtil.isNotBlank(request.getPrentCode())) {
            if (Validator.isNumber(request.getPrentCode())) {
                userRelationshipService.save(EbUserRelationshipEntity.builder()
                        .uid(Long.valueOf(user.getId())).pId(Long.valueOf(request.getPrentId()))
                        .isFirstOrder(1).isEstablish(0).build());
            } else {
                // 绑定推荐人
                if (StrUtil.isNotBlank(request.getPrentCode())) {
                    request.setPrentCode(RC4Util.decrypt(Long.parseLong(request.getPrentCode())));
//                    if (Validator.isNumber(request.getPrentCode())) {
//                        return CommonResult.failed("推荐信息格式不对");
//                    }
                    if (String.valueOf(user.getId()).equalsIgnoreCase(request.getPrentCode())) {
                        return CommonResult.failed("不能推荐自己");
                    }
                    // TODO 邀请待完善
                    userRelationshipService.save(EbUserRelationshipEntity.builder()
                            .uid(Long.valueOf(user.getId())).pId(Long.valueOf(request.getPrentCode()))
                            .isFirstOrder(1).isEstablish(0).createTime(LocalDateTime.now()).build());
                }
            }
        }

        return CommonResult.success(user.getId());
    }

    @Operation(summary = "用户信息")
    @RequestMapping(value = "/info", method = RequestMethod.GET)
    public CommonResult<UserInfoResponse> getUserCenter() {
        return CommonResult.success(userService.getUserInfo());
    }

    @Operation(summary = "换绑手机号获取用户手机号验证码")
    @RequestMapping(value = "/phone/code", method = RequestMethod.POST)
    public CommonResult<String> getCurrentPhoneCode() {
        if (userService.getCurrentPhoneCode()) {
            return CommonResult.success();
        }
        return CommonResult.failed();
    }

    @Operation(summary = "换绑手机号获取验证码")
    @RequestMapping(value = "/update/binding/phone/code", method = RequestMethod.POST)
    public CommonResult<String> updatePhoneCode(@RequestBody @Validated UserBindingPhoneUpdateRequest request) {
        if (userService.updatePhoneCode(request)) {
            return CommonResult.success();
        }
        return CommonResult.failed();
    }

    @Operation(summary = "换绑手机号")
    @RequestMapping(value = "/update/binding", method = RequestMethod.POST)
    public CommonResult<String> updatePhone(@RequestBody @Validated UserBindingPhoneUpdateRequest request) {
        if (userService.updatePhone(request)) {
            return CommonResult.success();
        }
        return CommonResult.failed();
    }

    @Operation(summary = "用户注销数据前置")
    @RequestMapping(value = "/logoff/before", method = RequestMethod.GET)
    public CommonResult<UserLogoffBeforeResponse> logoffBefore() {
        return CommonResult.success(userService.logoffBefore());
    }

    @Operation(summary = "用户注销")
    @RequestMapping(value = "/logoff", method = RequestMethod.POST)
    public CommonResult<String> logoff() {
        if (userService.logoff()) {
            return CommonResult.success();
        }
        return CommonResult.failed();
    }
}



